﻿using System;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using NewLife.Collections;

namespace NewLife.Reflection
{
    /// <summary>快速调用构造函数。基于DynamicMethod和Emit实现。</summary>
    public class ConstructorInfoX : MemberInfoX
    {
        #region 属性
        private ConstructorInfo _Constructor;
        /// <summary>目标方法</summary>
        public ConstructorInfo Constructor
        {
            get { return _Constructor; }
            private set { _Constructor = value; }
        }

        FastHandler _Handler;
        /// <summary>快速调用委托，延迟到首次使用才创建</summary>
        FastHandler Handler
        {
            get
            {
                //if (_Handler == null) _Handler = CreateDelegate<FastCreateInstanceHandler>(Constructor, typeof(Object), new Type[] { typeof(Object[]) });
                if (_Handler == null) _Handler = GetConstructorInvoker(Constructor);
                return _Handler;
            }
        }
        #endregion

        #region 扩展属性
        //private Type[] _ParamTypes;
        ///// <summary>参数类型数组</summary>
        //public Type[] ParamTypes
        //{
        //    get
        //    {
        //        if (_ParamTypes == null)
        //        {
        //            _ParamTypes = Type.EmptyTypes;

        //            ParameterInfo[] pis = Constructor.GetParameters();
        //            if (pis != null && pis.Length > 0)
        //            {
        //                List<Type> list = new List<Type>();
        //                foreach (ParameterInfo item in pis)
        //                {
        //                    list.Add(item.ParameterType);
        //                }
        //                _ParamTypes = list.ToArray();
        //            }
        //        }
        //        return _ParamTypes;
        //    }
        //}
        #endregion

        #region 构造
        private ConstructorInfoX(ConstructorInfo constructor) : base(constructor) { Constructor = constructor; }

        private static DictionaryCache<ConstructorInfo, ConstructorInfoX> cache = new DictionaryCache<ConstructorInfo, ConstructorInfoX>();
        /// <summary>创建</summary>
        /// <param name="constructor"></param>
        /// <returns></returns>
        public static ConstructorInfoX Create(ConstructorInfo constructor)
        {
            if (constructor == null) return null;

            return cache.GetItem(constructor, delegate(ConstructorInfo key)
            {
                return new ConstructorInfoX(key);
            });
        }

        /// <summary>创建</summary>
        /// <param name="type">类型</param>
        /// <param name="types"></param>
        /// <returns></returns>
        public static ConstructorInfoX Create(Type type, Type[] types)
        {
            ConstructorInfo constructor = type.GetConstructor(types);
            if (constructor == null) constructor = type.GetConstructor(DefaultBinding, null, types, null);
            if (constructor != null) return Create(constructor);

            //ListX<ConstructorInfo> list = TypeX.Create(type).Constructors;
            //if (list != null && list.Count > 0)
            //{
            //    if (types == null || types.Length <= 1) return list[0];

            //    ListX<ConstructorInfo> list2 = new ListX<ConstructorInfo>();
            //    foreach (ConstructorInfo item in list)
            //    {
            //        ParameterInfo[] ps = item.GetParameters();
            //        if (ps == null || ps.Length < 1 || ps.Length != types.Length) continue;

            //        for (int i = 0; i < ps.Length; i++)
            //        {

            //        }
            //    }
            //}

            //// 基本不可能的错误，因为每个类都会有构造函数
            //throw new Exception("无法找到构造函数！");

            return null;
        }

        /// <summary>创建</summary>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public static ConstructorInfoX Create(Type type)
        {
            return Create(type, Type.EmptyTypes);
        }
        #endregion

        #region 创建动态方法
        delegate Object FastHandler(Object[] parameters);

        private static FastHandler GetConstructorInvoker(ConstructorInfo constructor)
        {
            // 定义一个没有名字的动态方法。
            // 关联到模块，并且跳过JIT可见性检查，可以访问所有类型的所有成员
            DynamicMethod dynamicMethod = new DynamicMethod(String.Empty, typeof(Object), new Type[] { typeof(Object[]) }, constructor.DeclaringType.Module, true);
            var il = dynamicMethod.GetILGenerator();

            Type target = constructor.DeclaringType;
            if (target.IsValueType)
                il.NewValueType(target).BoxIfValueType(target).Ret();
            else if (target.IsArray)
                il.PushParams(0, new Type[] { typeof(Int32) }).NewArray(target.GetElementType()).Ret();
            else
                il.PushParams(0, constructor).NewObj(constructor).Ret();

            return (FastHandler)dynamicMethod.CreateDelegate(typeof(FastHandler));
        }
        #endregion

        #region 调用
        /// <summary>创建实例</summary>
        /// <param name="parameters">参数数组</param>
        /// <returns></returns>
        [DebuggerStepThrough]
        public override Object CreateInstance(params Object[] parameters)
        {
            return Handler.Invoke(parameters);
        }
        #endregion

        #region 类型转换
        /// <summary>类型转换</summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static implicit operator ConstructorInfo(ConstructorInfoX obj)
        {
            return obj != null ? obj.Constructor : null;
        }

        /// <summary>类型转换</summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static implicit operator ConstructorInfoX(ConstructorInfo obj)
        {
            return obj != null ? Create(obj) : null;
        }
        #endregion
    }
}
